package com.rjkj.medicalwaste.uncaught

import android.content.Context
import android.os.Build
import android.os.Environment
import android.util.Log
import android.widget.Toast
import androidx.core.content.ContextCompat
import com.alibaba.fastjson.JSONObject
import com.google.gson.Gson
import com.rjkj.medicalwaste.MWApplication
import com.rjkj.medicalwaste.bean.SettingBean
import com.rjkj.medicalwaste.network.retrofit.Api
import com.rjkj.medicalwaste.utils.AppPrefsUtils
import com.rjkj.medicalwaste.utils.BaseConstant
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.io.File
import java.io.FileWriter
import java.io.IOException
import java.io.PrintWriter
import java.util.*
import kotlin.system.exitProcess

class AppException : ExceptionListener() {
    override fun before() {
        super.before()
        Toast.makeText(
            MWApplication.getApp(), "很抱歉,程序出现异常,即将退出.",
            Toast.LENGTH_SHORT
        ).show()
        Log.e("TAG", "before: ")
    }

    override fun after() {
        super.after()
        Log.e("TAG", "after: ")
    }

    override fun fix(thread: Thread?, throwable: Throwable, context: Context?): Boolean {
        saveCrashInfoToFile(throwable)
        return true
    }

    /**
     * 保存错误信息到文件中
     * @param ex
     */
    private fun saveCrashInfoToFile(ex: Throwable) {
        val logPath: String
        if (Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED
            )
        ) {
            logPath = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                (ContextCompat.getExternalFilesDirs(MWApplication.getApp(), null)[0]
                    .absolutePath
                        + File.separator
                        + File.separator
                    .toString() + "log")
            } else {
                (Environment.getExternalStorageDirectory()
                    .absolutePath
                        + File.separator
                        + File.separator
                    .toString() + "log")
            }

            Log.e("PATH", "---------------------: $logPath")
            val file = File(logPath)
            if (!file.exists()) {
                file.mkdirs()
            }
            try {
                val fw = FileWriter(
                    logPath + File.separator
                        .toString() + "xlberror.log", true
                )
                fw.write(Date().toString() + "\n")
                val stackTrace = ex.stackTrace
                fw.write(ex.message + "\n")
                for (i in stackTrace.indices) {
                    fw.write(
                        ("file:" + stackTrace[i].fileName + " class:"
                                + stackTrace[i].className + " method:"
                                + stackTrace[i].methodName + " line:"
                                + stackTrace[i].lineNumber + "\n")
                    )
                }
                val printWriter = PrintWriter(fw)
                ex.printStackTrace(printWriter)
                var exCause = ex.cause
                while (exCause != null) {
                    exCause.printStackTrace(printWriter)
                    exCause = exCause.cause
                }
                fw.write("\n")
                fw.close()
                printWriter.close()
                // 上传错误信息到服务器
                uploadToServer(ex)
            } catch (e: IOException) {
                Log.e("crash handler", "load file failed...", e.cause)
            } finally {
                GlobalScope.launch {
                    delay(2000L)
                    exitProcess(0)
                }
            }
        }
        ex.printStackTrace()

    }

    private fun uploadToServer(ex: Throwable) {
        GlobalScope.launch {
            try {
                val jsonObject = JSONObject()
                jsonObject["deviceSN"] = Gson().fromJson(
                    AppPrefsUtils.getString(BaseConstant.SETTING),
                    SettingBean::class.java
                ).serialNum
                jsonObject["hospitalId"] = AppPrefsUtils.getString(BaseConstant.HOSPITAL_ID)
                jsonObject["errorMessage"] = ex.cause.toString()
                Api.sendStack(jsonObject)
            } catch (e: Throwable) {

            }
        }
    }
}